#include "QSocketViewerProtocol.h"

QSocketViewerProtocol::QSocketViewerProtocol(QTcpSocket* socket)
{
	this->socket = socket;
}

QSocketViewerProtocol::QSocketViewerProtocol()
{
	server = new QTcpServer();
	socket = new QTcpSocket();
	sizesum = 0;
}

QSocketViewerProtocol::~QSocketViewerProtocol()
{
}

float* QSocketViewerProtocol::getLocationData()
{
	return ldata;
}

int QSocketViewerProtocol::receive()
{
	puts("Start receiveing data\n");

#ifdef TEMP
	float *temp = ldata;
#endif

	puts("Sent request\n");
	int messageType;
	if (!socket->waitForReadyRead() && socket->atEnd())
	{
		throw NetworkException("Error waitreadyread");
	}

	if (socket->read((char*) &messageType, sizeof(int)) == -1)
	{
		throw NetworkException("Error on recieve messageType");
	}

	printf("messageType: %d\n", messageType);

	if (socket->read((char*) &count, sizeof(int)) == -1)
	{
		throw NetworkException("Error on recieve count");
	}

	printf("count: %d\n", count);

	switch (messageType)
	{
	case ADD_ELEMENTS:
		newElements.clear();
		for (int i = 0; i < count; ++i)
		{
			ElementData temp = readElementData();
			printf("recieve: %d\n", temp.getDataCount());
			newElements.append(temp);
			puts("Got new element data!");
		}
		break;
	case DELETE_ELEMENTS:

		break;
	case CHANGE_ELEMENTS:
		ldata = new float[count * 16];
		for (int i = 0; i < count; ++i)
		{

			printf("%d\n", socket->state());

			if (!socket->waitForReadyRead() && socket->atEnd())
			{
				throw NetworkException("Getting array: Error on waitforready");
			}
			puts("Maybe sex on the beach?");
			if (socket->read((char*) (ldata + (sizeof(float) * 16 * i)),
					sizeof(float) * 16) == -1)
			{
				throw NetworkException("Error on recieve transformation matrix");
			}
		}

		break;
	}
	for (int i = 0; i < count * 16; ++i)
	{
		if (i % 16 == 0)
			printf("\n");
		printf("%.2lf ", ldata[i]);
	}
	printf("\n");

#ifdef TEMP
	delete []temp;
#endif

	return messageType;
}

void QSocketViewerProtocol::connect(QString s)
{
	puts("Connecting");
	QHostAddress addr(s);
	socket->connectToHost(addr, PORT);
	puts("Connected");
}

void QSocketViewerProtocol::bind()
{
	puts("Trying to bind socket!");
	if (!server->listen(QHostAddress::Any, PORT))
	{
		throw NetworkException("Failed to bind socket!");
	}
}

void QSocketViewerProtocol::close()
{
	puts("Closing the socket");
	if (socket->state() == QAbstractSocket::ConnectedState)
		socket->close();
	puts("Closed socket");
}

ViewerProtocol* QSocketViewerProtocol::acceptConnection()
{
	server->waitForNewConnection(-1);
	socket = server->nextPendingConnection();
	ViewerProtocol* protocol = new QSocketViewerProtocol(socket);
	puts("Client connected...");
	return protocol;
}

void QSocketViewerProtocol::sendMessage(int type, int count)
{
	if (type > 1) exit(1);
	printf("Sending message %d %d\n", type, count);
	if (socket->write((const char*) &type, sizeof(int)) == -1)
	{
		throw NetworkException("Error on sending type");
	}
	if (socket->write((const char*) &count, sizeof(int)) == -1)
	{
		throw NetworkException("Error on sending count");
	}
	puts("Sent message\n");
	socket->flush();
	sizesum += sizeof(int)*2;
}

void QSocketViewerProtocol::sendObjects(const void *data, int size)
{
	sizesum += size;
	puts("Sending data");
	if (socket->write((const char*) data, size) == -1)
	{
		throw NetworkException("Error on sending objects");
	}
	socket->flush();
	printf("Data sent: %d\n",sizesum);
}

void QSocketViewerProtocol::waitRequest()
{
	int request;
	if (!socket->waitForReadyRead() && socket->atEnd())
	{
		throw NetworkException("waitRequest: Error on waitready");
	}
	if (socket->read((char *) &request, sizeof(int)) == -1)
	{
		throw NetworkException("Error on waitRequest");
	}

	printf("%d\n", request);
}

int QSocketViewerProtocol::getCount()
{
	return count;
}

ElementData QSocketViewerProtocol::getNewElement(int index)
{
	ElementData temp(newElements[index]);
	return temp;
}

ElementData QSocketViewerProtocol::readElementData()
{
	ElementType etype;
	if (socket->read((char*) &etype, sizeof(ElementType)) == -1)
	{
		throw NetworkException("Error on receive transformation matrix");
	}
	ElementData edata(etype);
	unsigned char *color = new unsigned char[3];
	if (socket->read((char*) color, sizeof(unsigned char) * 3) == -1)
	{
		delete [] color;
		throw NetworkException("Error on recieve transformation matrix");
	}
	edata.setColor(color[0],color[1],color[2]);
	delete [] color;

	float* tm = new float[16];
	if (socket->read((char*) tm, sizeof(float) * 16) == -1)
	{
		throw NetworkException("Error on recieve transformation matrix");
	}
	edata.setTransformationMatrix(tm);
	delete[] tm;
	int dataCount;
	if (socket->read((char*) &dataCount, sizeof(int)) == -1)
	{
		throw NetworkException("Error on recieve transformation matrix");
	}
	printf(" dataCount: %d\n", dataCount);
	tm = new float[dataCount];
	if (socket->read((char*) tm, sizeof(float) * dataCount) == -1)
	{
		throw NetworkException("Error on recieve transformation matrix");
	}
	edata.setData(dataCount, tm);
	return edata;
}

void QSocketViewerProtocol::writeElementData(const ElementData edata)
{
	ElementType etype = edata.getElementType();
	sendObjects(&etype, sizeof(ElementType));
	sendObjects(edata.getColor(), sizeof(char) * 3);
	sendObjects(edata.getTransformationMatrix(), sizeof(float) * 16);
	//	int *datacount = new int;
	//	*datacount = edata.dataCount;
	if (etype != MeshType) {
		int x = edata.getDataCount();
		sendObjects(&x, sizeof(int));
		sendObjects(edata.getData(), sizeof(float) * x);
	} else {
		int x = strlen(edata.getMeshType()) + 1;
		sendObjects(&x, sizeof(int));
		sendObjects(edata.getMeshType(), sizeof(int));
	}
}

void QSocketViewerProtocol::sendRequest()
{
	int request = 256;
	if (socket->write((char *) &request, sizeof(int)) == -1)
	{
		throw NetworkException("Error on waitRequest");
	}
}
